package com.dg.gaming.tictactoe.common {
    import com.dg.gaming.api.common.GameModel;
    import com.dg.gaming.api.common.msg.Msg;
    import com.dg.gaming.api.common.util.DGUtils;

    import nanoxml.XMLElement;

    public class TicTacToeModel extends GameModel {
        // Declare constans to define model
        public static const BLANK:int = -1;

        public static const X:int = 0;

        public static const O:int = 1;

        // model (2 dimensional int array)
        private var data:Array = [[ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ]];

        public function TicTacToeModel(gameType:int = -1) {
            super(gameType);
            reset();
        }

        /**
         * Update the state of the model from the message.
         *
         * @see com.dg.gaming.api.common.GameModel#setState(nanoxml.XMLElement)
         */
        public override function setState(message:XMLElement):void {
            var alldata:Array = DGUtils.convertToIntArray(message.getContent());
            data = DGUtils.convertTo2DArray(alldata, 3, 3);
            refreshObservers();
        }

        // reset the model back to zeros
        public function reset():void {
            for (var x:int = 0; x < 3; x++) {
                for (var y:int = 0; y < 3; y++) {
                    data[x][y] = BLANK;
                }
            }
            refreshObservers();
        }

        // return data at a particular point
        public function getData(x:int, y:int):int {
            return data[x][y];
        }

        // set data at a point
        public function setData(x:int, y:int, value:int):void {
            data[x][y] = value;
            refreshObservers(); // update any views on this model
        }

        // return true if the game is won by this player
        public function isGameWon(player:int):Boolean {
            // check y axis
            for (var x1:int = 0; x1 < 3; x1++) {
                var count1:int = 0;
                for (var y1:int = 0; y1 < 3; y1++) {
                    if (data[x1][y1] == player)
                        count1++;
                }
                if (count1 == 3)
                    return true;
            }
            // check x axis
            for (var y2:int = 0; y2 < 3; y2++) {
                var count2:int = 0;
                for (var x2:int = 0; x2 < 3; x2++) {
                    if (data[x2][y2] == player)
                        count2++;
                }
                if (count2 == 3)
                    return true;
            }
            // check diagonals
            if (data[0][0] == player && data[1][1] == player && data[2][2] == player)
                return true;
            if (data[0][2] == player && data[1][1] == player && data[2][0] == player)
                return true;
            return false;
        }

        // return true if all 9 spaces are taken
        public function isNoCellsLeft():Boolean {
            var count:int = 0;
            // check each cell
            for (var x:int = 0; x < 3; x++) {
                for (var y:int = 0; y < 3; y++) {
                    if (data[x][y] != BLANK)
                        count++;
                }
            }
            return (count == 9); // if all 9 spaces filled return true
        }

        /**
         * Flatten tic-tac-toe data.
         *
         * @see com.dg.gaming.api.common.comm.ITransmittable#flatten()
         */
        public override function flatten():XMLElement {
            var message:XMLElement = new XMLElement();
            message.name = Msg.MODEL;
            // Flatten 2d data to a single array and then to a String
            var alldata:Array = DGUtils.convertTo1DArray(data);
            var allDataStr:String = DGUtils.valueOfArray(alldata);
            message.setContent(allDataStr);

            return message;
        }
    }
}